package com.itheima.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.token.TokenService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import javax.sql.DataSource;

/**
 * 认证服务配置类
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    @Bean
    public JdbcClientDetailsService jdbcClientDetailsService(){
        return new JdbcClientDetailsService(dataSource);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(jdbcClientDetailsService());
    }



    /**
     *
     * 客户端端的配置信息 --------> 有哪些客户端可以介入认证 ;
     * authorization_code : 授权码模式 ;
     * password : 密码模式
     *
     * @throws Exception
     */
    /*@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()  //在内存中存放客户端信息
                .withClient("nc_client_app")   //接入客户端ID
                .secret("$2a$10$VFFZb.weUMXvAxhlNNzFzesqzzzvccH3u9vm4tTYGLyksl99gnJN.") //客户端的密码
                .scopes("all")   //作用范围
                .redirectUris("http://localhost")   //重定向地址;
                .authorizedGrantTypes("authorization_code","password")   //OAuth2模式 ;

                .and()

                .withClient("nc_client_pc")
                .secret("$2a$10$VFFZb.weUMXvAxhlNNzFzesqzzzvccH3u9vm4tTYGLyksl99gnJN.")
                .scopes("all")
                .redirectUris("http://localhost") //重定向地址;
                .authorizedGrantTypes("authorization_code","password");

    }*/












    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll")   //tokenkey当使用JwtToken且使用非对称加密时，资源服务用于获取公钥而开放的，这里指这个 endpoint完全公开
                .checkTokenAccess("permitAll") //checkToken这个endpoint完全公开
                .allowFormAuthenticationForClients(); //允许表单认证(密码/授权码模式认证)
    }


    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .tokenServices(tokenService())
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }



    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private TokenStore tokenStore;
    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;
    /**
     * 控制令牌配置信息
     * @return
     */
    @Bean
    public AuthorizationServerTokenServices tokenService(){
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setAuthenticationManager(authenticationManager);
        tokenServices.setClientDetailsService(clientDetailsService);//客户端详情服务配置
        tokenServices.setTokenStore(tokenStore); //令牌存储---

//        tokenServices.setAccessTokenValiditySeconds(7200);//access_token的有效期---->可以不设置,有默认值的 12小时 ;
//        tokenServices.setRefreshTokenValiditySeconds(259200);//refresh_token的有效期---->可以不设置,有默认值30天 ;

        tokenServices.setTokenEnhancer(jwtAccessTokenConverter); //对原始的令牌进行增强 ------> jwt
        tokenServices.setSupportRefreshToken(true); //是否支持刷新令牌

        return tokenServices;
    }


}
